package org.jeecg.modules.rental.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.jeecg.boot.starter.lock.client.RedissonLockClient;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.modules.rental.cache.StoreCache;
import org.jeecg.modules.rental.entity.RentalStore;
import org.jeecg.modules.rental.mapper.RentalStoreMapper;
import org.jeecg.modules.rental.service.IRentalConfigService;
import org.jeecg.modules.rental.service.IRentalStoreService;
import org.jeecg.modules.rental.util.OrderSnUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.data.geo.Circle;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.Metrics;
import org.springframework.data.geo.Point;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * @Description: 租车网点
 * @Author: sean
 * @Date: 2022-03-29
 * @Version: V1.0
 */

@Slf4j
@Service
@RequiredArgsConstructor
public class RentalStoreServiceImpl extends ServiceImpl<RentalStoreMapper, RentalStore> implements IRentalStoreService {

    private final ISysBaseAPI sysBaseAPI;

    private final OrderSnUtil orderSnUtil;

    private final RedissonLockClient redissonLock;

    private final IRentalConfigService rentalConfigService;

    private final StoreCache storeCache;

//    @Override
//    @DataOrgScope(orgField="t1.sys_org_code")
//    public Page<RentalStore> pageList(Page page, RentalStore req) {
//        List<OrderItem> orderItemList = page.getOrders();
//        orderItemList.forEach(item -> {
//            item.setColumn("t1." + item.getColumn());
//        });
//        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
//        //TODO 数据权限查询
////        if(DataScopeEnums.DATA_SCOPE_STORE.getValue().equals(loginUser.getRoleDataScope())){
////            req.setDataScopeSql(" AND ( t1.person_charge_id = " + loginUser.getId() + ")" );
////        }
//        Page<RentalStore> adminWithdrawPage = baseMapper.selectJoinPage(page, req);
//        return adminWithdrawPage;
//    }

    @Override
    public void add(RentalStore req) {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        String lastMerchantCode = baseMapper
                .lastMerchantCode(new QueryWrapper<RentalStore>().eq("sys_org_code", loginUser.getOrgCode()));
        String lockName = "add:rental_store:"+ loginUser.getOrgCode() + ":lock";
        if (redissonLock.tryLock(lockName, -1, 1)) {
            // 获取商户编号
            String nextMerchantCode = orderSnUtil.getMerchantCode(lastMerchantCode);
            req.setMeshPointsCode(nextMerchantCode);
            req.setMeshPointsType(1);
            baseMapper.insert(req);
            storeCache.addLocation(
                    new Point(Double.parseDouble(req.getLongitude()) , Double.parseDouble(req.getLatitude())),
                    req.getId().toString());
            redissonLock.unlock(lockName);
        } else {
            throw new JeecgBootException("rentalstore.service.lock.fail");
        }
    }

    @Override
    public void edit(RentalStore req) {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        if (loginUser.getOrgCode() == null) {
            throw new JeecgBootException("rentalstore.service.account.not.added");
        }
        RentalStore rentalStore = baseMapper.selectById(req.getId());
        if (rentalStore == null) {
            throw new JeecgBootException("rentalstore.service.store.not.found");
        }
        if(ObjectUtil.isEmpty(req.getLatitude()) && ObjectUtil.isEmpty(req.getLongitude()) ){
            req.setLatitude(rentalStore.getLatitude());
            req.setLongitude(rentalStore.getLongitude());
        }
        BeanUtils.copyProperties(req, rentalStore);
        storeCache.addLocation(
                new Point(Double.parseDouble(rentalStore.getLongitude()) , Double.parseDouble(rentalStore.getLatitude())),
                rentalStore.getId().toString());
        baseMapper.updateById(rentalStore);
    }

    @Override

    public void modifyState(String id, Integer meshPointsType) {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        if (loginUser.getOrgCode() == null) {
            throw new JeecgBootException("rentalstore.service.account.not.added");
        }
        RentalStore rentalStore = baseMapper.selectById(id);
        if (rentalStore == null) {
            throw new JeecgBootException("rentalstore.service.store.not.found");
        }
        if (!loginUser.getOrgCode().equals(rentalStore.getSysOrgCode())) {
            throw new JeecgBootException("rentalstore.service.store.not.belong");
        }
        rentalStore.setMeshPointsType(meshPointsType);
        baseMapper.updateById(rentalStore);
    }



    @Override
    public List<RentalStore> shopListByLocation(Double latitude, Double longitude, QueryWrapper wrapper) {
        //获取网点查询距离限制
        double distanceLimit = 0.0; //无限制
        List<String> storeIds = new ArrayList<>();
        if(distanceLimit > 0.0){
            //有距离限制, 从缓存中区附近的网点
            Point point = new Point(longitude, latitude);
            Circle circle = new Circle(point, new Distance(distanceLimit, Metrics.KILOMETERS));
            storeIds = storeCache.getNearby(circle, 30); //最后查30个门店
        }
        //无距离限制直接查询
        if(null != storeIds && !storeIds.isEmpty()){
            wrapper.in("id", storeIds);
        }
        List<RentalStore> list = baseMapper.selectList(wrapper);
        return list;
    }

//    @Override
//    @DataOrgScope(orgField="sys_org_code")
//    public List<RentalStore> selectJoinList(RentalStore req) {
//        return baseMapper.selectJoinList(req);
//    }

    @Override
    public void initCacheLocation() {
        List<RentalStore> rentalList = this.list(new QueryWrapper<RentalStore>().isNotNull("latitude").isNotNull("longitude"));
        storeCache.initLocation(rentalList);
    }

    @Override
    public List<Map<String, Object>> getAllStores() {
        QueryWrapper<RentalStore> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("id AS storeId", "mesh_points_name AS storeName");
        return this.baseMapper.selectMaps(queryWrapper);
    }

//    @Override
//    public ShopPointLocationDto shopByLocation(Double latitude, Double longitude, String orgCode) {
//        return baseMapper.shopByLocation(latitude, longitude, orgCode);
//    }

}
